package joe;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.system.MemoryUtil;
import org.tinylog.Logger;

public class ResourceMapFile implements Resource {
	private final @NotNull MappedByteBuffer mbb;

	public ResourceMapFile(@NotNull MappedByteBuffer mbb) {
		this.mbb = mbb;
	}

	public @NotNull MappedByteBuffer getMappedByteBuffer() {
		return mbb;
	}

	@Override
	public long getDataPtr() {
		return MemoryUtil.memAddress(mbb);
	}

	@Override
	public long getDataSize() {
		return mbb.remaining();
	}

	@Override
	public @NotNull Runnable getCleaner() {
		var mbb0 = mbb;
		return () -> UnsafeUtil.freeMappedByteBuffer(mbb0);
	}

	public static @Nullable MappedByteBuffer loadMapFile(@NotNull String path) {
		try (final var raf = new RandomAccessFile(path, "r"); var fc = raf.getChannel()) {
			return fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
		} catch (IOException e) {
			Logger.error(e, "ResourceMapFile: load file failed: {}", path);
			return null;
		}
	}

	public static @Nullable ResourceMapFile load(@NotNull String path) {
		var mbb = loadMapFile(path);
		return mbb != null ? new ResourceMapFile(mbb) : null;
	}
}
